#include "hal_data.h"

FSP_CPP_HEADER
void R_BSP_WarmStart(bsp_warm_start_event_t event);
FSP_CPP_FOOTER


/* 用户头文件包含 */
#include "led/bsp_led.h"
#include "debug_uart/bsp_debug_uart.h"
#include "dtc/bsp_dtc.h"


extern const uint32_t SRC_Buffer[BUFFER_SIZE];
extern uint32_t DST_Buffer[BUFFER_SIZE];
extern uint32_t Expected_DST_Buffer[BUFFER_SIZE];
extern volatile bool dtc_complete_transmission_sign;

uint8_t BufferCompare(const uint32_t *pBuffer1, const uint32_t *pBuffer2, uint16_t BufferLength);
void    BufferShow_HexData(const uint32_t *pBuffer, uint16_t BufferLength);


/* 按键按下标志 */
volatile bool key_sw2_press = false;

/* 按键中断回调函数 */
void icu_external_irq_callback(external_irq_callback_args_t *p_args)
{
    /* 判断中断通道 */
    if (9 == p_args->channel)
    {
        key_sw2_press = true;   // 按键SW2按下
    }
}

/*******************************************************************************************************************//**
 * main() is generated by the RA Configuration editor and is used to generate threads if an RTOS is used.  This function
 * is called by main() when no RTOS is used.
 **********************************************************************************************************************/
void hal_entry(void)
{
    /* TODO: add your own code here */
    uint8_t res;

    LED_Init();         // LED 初始化
    Debug_UART4_Init(); // SCI4 UART 调试串口初始化

    /* 初始化 DTC */
    DTC_Init();

    printf("这是一个 DTC 存储器到存储器的传输实验例程\r\n");
    printf("打开串口助手，查看接收窗口打印的相关提示信息\r\n");
    printf("按下按键 SW2 激活 DTC 传输\r\n");
    printf("观察板载LED灯，本实验使用两个LED灯来指示 DTC 传输结果\r\n");
    printf("- DTC 数据传输失败，则 LED1 亮（红色）\r\n");
    printf("- DTC 数据传输成功，则 LED2 亮（蓝色）\r\n");
    printf("--------------------------------------------\r\n");


    /* Open ICU module */
    R_ICU_ExternalIrqOpen(&g_external_irq9_ctrl, &g_external_irq9_cfg);
    /* 允许中断 */
    R_ICU_ExternalIrqEnable(&g_external_irq9_ctrl);


    /* 使能 DTC 模块 */
    R_DTC_Enable(&g_transfer_dtc_ctrl);

    /*************************************/
    /* 使用按键外部中断触发激活 DTC 传输 */
    /*************************************/

#ifndef USE_MY_TRANSFER_INFOR_CONFIG
    /* 根据 FSP 配置界面的传输信息进行传输 */

    /* 等待激活 DTC 传输 */
    for (uint16_t i = 0; i < 1; i++)
    {
        /* 等待按键按下，按键按下一次即激活一次 DTC 传输 */
        while (false == key_sw2_press);
        key_sw2_press = false;
        /* 等待本次传输完成 */
        R_BSP_SoftwareDelay(5, BSP_DELAY_UNITS_MILLISECONDS);   //加上延时确保传输完成
    }

#else   // 下面的这些是使用自定义的传输配置信息配置

#if (DTC_TRANSFER_MODE == DTC_TRANSFER_NORMAL_MODE)           //正常模式

    /* 等待激活 DTC 传输 */
    for (uint16_t i = 0; i < 1; i++)
    {
        /* 等待按键按下，按键按下一次即激活一次 DTC 传输 */
        while (false == key_sw2_press);
        key_sw2_press = false;
        /* 等待本次传输完成 */
        R_BSP_SoftwareDelay(5, BSP_DELAY_UNITS_MILLISECONDS);   //加上延时确保传输完成
    }

#elif (DTC_TRANSFER_MODE == DTC_TRANSFER_REPEAT_MODE)         //重复模式

    /* 等待激活 DTC 传输 */
    for (uint16_t i = 0; i < 4; i++)
    {
        /* 等待按键按下，按键按下一次即激活一次 DTC 传输 */
        while (false == key_sw2_press);
        key_sw2_press = false;
        /* 等待本次传输完成 */
        R_BSP_SoftwareDelay(5, BSP_DELAY_UNITS_MILLISECONDS);   //加上延时确保传输完成
    }

#elif (DTC_TRANSFER_MODE == DTC_TRANSFER_BLOCK_MODE)          //块模式

    /* 等待激活 DTC 传输 */
    for (uint16_t i = 0; i < 1; i++)
    {
        /* 等待按键按下，按键按下一次即激活一次 DTC 传输 */
        while (false == key_sw2_press);
        key_sw2_press = false;
        /* 等待本次传输完成 */
        R_BSP_SoftwareDelay(5, BSP_DELAY_UNITS_MILLISECONDS);   //加上延时确保传输完成
    }

#endif //DTC_TRANSFER_MODE

#endif //USE_MY_TRANSFER_INFOR_CONFIG


    /* 将传输后的数据与我们所期待的结果相比较 */
    res = BufferCompare(DST_Buffer, Expected_DST_Buffer, BUFFER_SIZE);

    printf("传输结果：");
    /* 根据两者数据的比较结果进行判断 */
    if( res != 0)
    {
        /* 源数据与传输后数据不相等时，LED1 亮（红色），表示传输失败 */
        LED1_ON;
        printf("<传输失败>\r\n");
    }
    else
    {
        /* 源数据与传输后数据相等时，LED1 亮（蓝色），表示传输成功 */
        LED2_ON;
        printf("<传输成功>\r\n");
    }

    printf("\r\nSRC:");
    BufferShow_HexData(SRC_Buffer, BUFFER_SIZE);
    printf("\r\nDST:（应与 Expected_DST 一致）");
    BufferShow_HexData(DST_Buffer, BUFFER_SIZE);
    printf("\r\nExpected_DST:");
    BufferShow_HexData(Expected_DST_Buffer, BUFFER_SIZE);

    while(1)
    {

    }


#if BSP_TZ_SECURE_BUILD
    /* Enter non-secure code */
    R_BSP_NonSecureEnter();
#endif
}


/* 返回 0 表示两个缓冲区数据一致
*/
uint8_t BufferCompare(const uint32_t *pBuffer1, const uint32_t *pBuffer2, uint16_t BufferLength)
{
    /* 数据长度递减 */
    while(BufferLength--)
    {
        /* 判断两个数据源是否对应相等 */
        if(*pBuffer1 != *pBuffer2)
        {
            /* 对应数据源不相等马上退出函数，并返回1 */
            return 1;
        }
        /* 递增两个数据源的地址指针 */
        pBuffer1++;
        pBuffer2++;
    }
    /* 完成判断并且对应数据相对 */
    return 0;
}

/* 打印缓冲区数据：十六进制格式
*/
void BufferShow_HexData(const uint32_t *pBuffer, uint16_t BufferLength)
{
    while(BufferLength)
    {
        if((BufferLength % 4) == 0)
            printf("\r\n\t");

        printf("0x%08X ", *pBuffer);

        pBuffer++;
        BufferLength--;
    }

    printf("\r\n");
}


/*******************************************************************************************************************//**
 * This function is called at various points during the startup process.  This implementation uses the event that is
 * called right before main() to set up the pins.
 *
 * @param[in]  event    Where at in the start up process the code is currently at
 **********************************************************************************************************************/
void R_BSP_WarmStart(bsp_warm_start_event_t event)
{
    if (BSP_WARM_START_RESET == event)
    {
#if BSP_FEATURE_FLASH_LP_VERSION != 0

        /* Enable reading from data flash. */
        R_FACI_LP->DFLCTL = 1U;

        /* Would normally have to wait tDSTOP(6us) for data flash recovery. Placing the enable here, before clock and
         * C runtime initialization, should negate the need for a delay since the initialization will typically take more than 6us. */
#endif
    }

    if (BSP_WARM_START_POST_C == event)
    {
        /* C runtime environment and system clocks are setup. */

        /* Configure pins. */
        R_IOPORT_Open (&g_ioport_ctrl, g_ioport.p_cfg);
    }
}

#if BSP_TZ_SECURE_BUILD

BSP_CMSE_NONSECURE_ENTRY void template_nonsecure_callable ();

/* Trustzone Secure Projects require at least one nonsecure callable function in order to build (Remove this if it is not required to build). */
BSP_CMSE_NONSECURE_ENTRY void template_nonsecure_callable ()
{

}
#endif
